package com.icee.myth.common;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;

/**
 *	抽象服务器类
 * @author liuxianke
 */
public abstract class AbstractServer implements Server {

	private int port; // Server的端口地址

	private ServerBootstrap bootstrap;
	private Channel bindChannel = null;

	private EventLoopGroup bossGroup;
	private EventLoopGroup workGroup;

	public AbstractServer() {
	}

	/**
	 * 使用帮助类ServerBootstrap准备启动网络服务
	 * 
	 * @param port
	 *            服务的端口
	 * @param childHandler
	 *            Netty 初始化通讯管道处理类
	 */
	public void init(int port, ChannelHandler childHandler) {
		this.port = port;

		// Start server with Nb of active threads = 2*NB CPU + 1 as maximum.
		final int workerCount = Runtime.getRuntime().availableProcessors() * 2 + 1;

		bossGroup = new NioEventLoopGroup();
		workGroup = new NioEventLoopGroup(workerCount);

		// Configure the server.
		bootstrap = new ServerBootstrap();
		bootstrap.group(bossGroup, workGroup);
		bootstrap.channel(NioServerSocketChannel.class);

		bootstrap.option(ChannelOption.SO_BACKLOG, 1024);	//指定了内核为此套接口排队的最大连接个数，netty默认100
		bootstrap.option(ChannelOption.TCP_NODELAY, true);	// 无延迟
		bootstrap.option(ChannelOption.SO_KEEPALIVE, true);	// 保持存活
		bootstrap.option(ChannelOption.SO_REUSEADDR, true);	// 重复利用地址
		bootstrap.option(ChannelOption.ALLOW_HALF_CLOSURE, true);	// 捕获远程主机强制关闭一个连接

		bootstrap.childHandler(childHandler);
	}

	@Override
	public void startServer() {
		// Bind and startOnlyOnce to accept incoming connections.
		ChannelFuture future =  bootstrap.bind(new InetSocketAddress(port));
		future.addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				System.out.println("server bind ok,port="+port);
				bindChannel = future.channel();
			}
		});
	}

	@Override
	public void closeServer() {
		if (bossGroup != null) {
			bossGroup.shutdownGracefully();
		}
		if (workGroup != null) {
			workGroup.shutdownGracefully();
		}
	}
}
